<?php

/**
 * Title: Thai Splitter Lib
 * Author: Suwicha Phuak-im
 * Email: suwichalala@gmail.com
 * Website: http://www.projecka.com
 */
class Segment {

    private $_input_string;
    private $_dictionary_array = array();
    private $_thcharacter_obj;
    private $_unicode_obj;
    private $_segmented_result = array();
	private $path;
    
    
    
    function __construct() {
		$this->path="../../../uploads/file/";
        include(dirname(dirname(dirname(__FILE__))).DIRECTORY_SEPARATOR."wordconvert".DIRECTORY_SEPARATOR."wordconvert.php");			
		include(dirname(__FILE__) .DIRECTORY_SEPARATOR.'thcharacter.php');
        include(dirname(__FILE__) . DIRECTORY_SEPARATOR .'unicode.php');
        $file_handle = fopen(dirname(__FILE__).DIRECTORY_SEPARATOR. 'dictionary' . DIRECTORY_SEPARATOR . 'dictionary.txt', "rb");
        while (!feof($file_handle)) {
            $line_of_text = fgets($file_handle); // ถ้าไม่ใส่ length จะเป็นตัดทีละบรรทัด
            $this->_dictionary_array[crc32(trim($line_of_text))] = trim($line_of_text);
        }
        fclose($file_handle);



        // Load Helper Class/
        $this->_unicode_obj = new Unicode();
        $this->_thcharacter_obj = new Thchracter();
    }

    private function clear_duplicated($string) {

        
        //หดรูปตัวอักษรซ้ำๆ//
        $input_string_split = $this->_unicode_obj->uni_strsplit($string);
        $previous_char = '';
        $previous_string = '';
        $dup_list_array = array();
        $dup_list_array_replace = array();
        foreach ($input_string_split as $current_char) {

            if ($previous_char == $current_char) {
                $previous_char = $current_char;
                $previous_string .= $current_char;
            } else {
                if (mb_strlen($previous_string) > 3) {
                    $dup_list_array[] = $previous_string;
                    $dup_list_array_replace[] = $current_char;
                    $string = str_replace($previous_string, $previous_char, $string);
                }
                $previous_char = $current_char;
                $previous_string = $current_char;
            }
        }
        if (mb_strlen($previous_string) > 3) {
            $dup_list_array[] = $previous_string;
            $dup_list_array_replace = $current_char;
        }
        return str_replace($dup_list_array, $dup_list_array_replace, $string);
    }



    public function get_segment_array($input_string,$fileatth=FALSE) {
      
       $line="";	
	  $this->_input_string="";		
	  $this->_segmented_result=array();
		if(file_exists($this->path.$fileatth))
		{
			$contents= new wordconvert();	
			$line=$contents->get_wordconvert($this->path.$fileatth);
			
		}
		//echo "line : ".$line;exit;				
        $this->_input_string = $input_string.$line;


        // ลบเครื่องหมายคำพูด, ตัวแบ่งประโยค //
        $this->_input_string = str_replace(array('\'', '‘', '’', '“', '”', '"', '-', '/', '(', ')', '{', '}', '...', '..', '…', '', ',', ':', '|', '\\'), '', $this->_input_string);
        // เปลี่ยน newline ให้กลายเป็น Space เพื่อที่ใช้สำหรับ Trim
        $this->_input_string = str_replace(array("\r", "\r\n", "\n"), ' ', $this->_input_string);


        // กำจัดซ้ำ //
        //$this->_input_string = $this->clear_duplicated($this->_input_string);


        // แยกประโยคจากช่องว่าง (~เผื่อไว้สำหรับภาษาอังกฤษ) //
        $this->_input_string_exploded = explode(' ', $this->_input_string);



        // Reverse Array สำหรับการใช้ Dictionary แบบ Reverse ใช้ฟังก์ชัน array_reverse() เพื่อกลับตำแหน่งของ element ใน array//
      
        foreach ($this->_input_string_exploded as $input_string_exploded_row) {
            $current_string_reverse_array = array_reverse($this->_unicode_obj->uni_strsplit(trim($input_string_exploded_row)));
				

		 
		
            $current_array_result = $this->_segment_by_dictionary_reverse($current_string_reverse_array);
            foreach ($current_array_result as $each_result) {
                if (trim($each_result) != '')
                    $this->_segmented_result[] = trim($each_result);
            }
        }

        // จัดการคำที่ตัดที่ยาวผิดปกติ (~อาจจะเป็นเพราะว่าพิมผิด) โดยการตัดตาม Dict แบบธรรมดา//
        $tmp_result = array();
        foreach ($this->_segmented_result as $result_row) {
            if (mb_strlen($result_row) > 10) {

                $current_string_array = $this->_unicode_obj->uni_strsplit(trim($result_row));
                $current_array_result = $this->_segment_by_dictionary($current_string_array);

                foreach ($current_array_result as $current_result_row) {
                    $tmp_result[] = trim($current_result_row);
                }
            } else {
                $tmp_result[] = $result_row;
            }
        }
      	//ตัด stopword ออก
		//$tmp_result=$this->_segment_clear_stopword($tmp_result);
		//$this->_segmented_result = $tmp_result;
        return $this->_segmented_result;
    }

	public function _segment_clear_stopword($segment_result){
		$result=mysql_query("select * from tb_stopword");		
		while($item=mysql_fetch_assoc($result)){
			$row[]=$item['name'];			
		}
		$stopWord=array_intersect($segment_result,$row);
		//print_r($stopWord);
		foreach($stopWord as $item)
		{ //ตัด stopword ออก
			unset($segment_result[array_search($item,$segment_result)]);
		}	
		return $ans=array('segment_result'=>$segment_result,'stopWord'=>$stopWord);
			
		//return $segment_result;
	}
	private function _segement_tb_index()
	{
		// ตารางช้อมูลตั้งต้น ได้แก่  ความถี่ของคำ ,ประเภทปัญหา,ค่า df, ค่า idf
		$result=mysql_query("select * from tb_index");
		while($item=mysql_fetch_assoc($result)){
			$tb_index[$item['id']]=$item['name'];
		}
		return $tb_index;
	}
	public function _segment_document_frequency($segment_result)
	{
		/**** หาความถี่ของเอกสาร  **/ 
		$tb_index=$this->_segement_tb_index();		
		array_walk($segment_result,'change_keyword');
		$arr_index=array_count_values($tb_index);		// นับจำนวนคำที่พบในอาร์เรย์
		$arr_result=array_count_values($segment_result);// นับจำนวนคำที่พบในอาร์เรย์
		$arr_count=array_intersect_key($arr_result, $arr_index); // เลือกค่าที่มีค่าคีย์ตรงกัน

		return $arr_count;
	}
	public function _segment_document_matrix($arr_count)
	{
		$tb_index=$this->_segement_tb_index();	
		$arr_weight=$arr_count;	
		array_walk($arr_weight,'get_weight');// หาค่า idf และ weigth 
		$arr_key=array_keys($arr_weight);		
		$arr_value=array_values($arr_weight);
		$arr_index_id=array_intersect($tb_index,$arr_key);
		$arr_index_id=array_keys($arr_index_id);
		$arr_combine=array_combine($arr_index_id,$arr_value);
		
		return $arr_combine;
	}
	
	public function _segment_count_keyword($segment_result)
	{
		
		$arr_count=$this->_segment_document_frequency($segment_result);
		// ข้อมูลต้นแบบ (D) :key=keyword ของแต่ละปัญหาม ,value=weight;
		$arr_combine=$this->_segment_document_matrix($arr_count);
		//ข้อมูลต้นแบบ (D) : เอา น้ำหนักมายกกำลังสอง
		$arr_combine_pow=array_map('get_pow',$arr_combine);
		// ข้อมูลต้นแบบ (D) :เอาน้ำหนักทุกในอาร์เรย์มาบวกัน
		$query_combine_pow_sum=array_sum($arr_combine_pow);		
		// รีเทิร์นค่า คีย์ทั้งหมด
		$arr_index_id=array_keys($arr_combine);
		/// +++++ สิ้นสุดกระบวนการเตรียมข้อมูล ++++ 

		// +++++ inner product +++++
		$index_id=implode(',',$arr_index_id);
		$rs=mysql_query("select * from tb_term where index_id in(".$index_id.") order by doc_id,index_id");		
		while($tb_term=mysql_fetch_assoc($rs)){
								
			if(array_key_exists($tb_term['index_id'],$arr_combine))
			{
					//inner product
					$D1=$tb_term['weight'];
					$Q1=$arr_combine[$tb_term['index_id']];
					$arr_doc_inner[$tb_term['doc_id']][$tb_term['index_id']]=round($tb_term['weight']*$arr_combine[$tb_term['index_id']],5);									
					$arr_sum[$tb_term['doc_id']]=array_sum($arr_doc_inner[$tb_term['doc_id']]);
			
					if($tb_term['weight']!=0)
					{
						$arr_doc_inner_cal[$tb_term['doc_id']][$tb_term['index_id']]="(".$D1."x".$Q1.")";
					}
					
					
			}
			
		}	
								
			
			$max_val=max($arr_sum);	// ได้ค่ามาก inner product มากที่สุด				
			$doc_id=array_keys($arr_sum,$max_val);	//หาเอกสารที่มีค่ามากที่สุด			
			$problem_name=$this->_segment_similality_document($doc_id);								
			$answer=array('doc_inner'=>$arr_doc_inner
						 ,'doc_inner_sum'=>$arr_sum
						 ,'doc_inner_cal'=>$arr_doc_inner_cal
						 ,'doc_inner_max'=>$max_val
						 ,'doc_inner_similality'=>$doc_id
						 ,'doc_inner_problem_type'=>$problem_name
						 ,'query_combine_pow_sum'=>$query_combine_pow_sum
						 );
		return $answer;
		
	}
	public function _segement_similality_cosine($query_pow_sum,$arr_doc_inner)
	{
		// $arr_doc_inner (D*Q)
		// $query_pow_sum ค่าน้ำหนักของแต่ query ยกกำลังสอง	
		$query_pow_sum_sqrt=sqrt($query_pow_sum);	
		$rs=mysql_query("select *,ROUND(POWER(weight,2),4) as doc_pow from tb_term order by doc_id,index_id");
		while($tb_term=mysql_fetch_assoc($rs))
		{
			//ค่าของน้ำหนัก ในแต่ละ doc ยกกำลังสอง	
			$arr_doc_pow[$tb_term['doc_id']][$tb_term['index_id']]=$tb_term['doc_pow'];
			//ผลรวมของค่าของน้ำหนัก ของทุก keyword ยกกำลังสอง	
			$arr_doc_pow_sum[$tb_term['doc_id']]=array_sum($arr_doc_pow[$tb_term['doc_id']]);			
			if($arr_doc_inner[$tb_term['doc_id']]!=0 && $arr_doc_pow_sum[$tb_term['doc_id']]!=0 && $query_pow_sum!=0){
				$arr_doc_pow_sum_sqrt[$tb_term['doc_id']]	=sqrt($arr_doc_pow_sum[$tb_term['doc_id']]);
				$arr_doc_cosine[$tb_term['doc_id']]=round($arr_doc_inner[$tb_term['doc_id']]/(sqrt($arr_doc_pow_sum[$tb_term['doc_id']])*$query_pow_sum_sqrt),4);				
			}	
			
		}
		$max_val=max($arr_doc_cosine);	// ได้ค่ามาก inner product มากที่สุด				
		$doc_id=array_keys($arr_doc_cosine,$max_val);	//หาเอกสารที่มีค่ามากที่สุด			
		$problem_name=$this->_segment_similality_document($doc_id);	
		$answer=array('doc_cosine'=>$arr_doc_cosine
					 ,'doc_pow_sum_sqrt'=>$arr_doc_pow_sum_sqrt
					 ,'query_pow_sum_sqrt'=>$query_pow_sum_sqrt
					 ,'doc_cosine_max'=>$max_val
					 ,'doc_cosine_similality'=>$doc_id
					 ,'doc_cosine_problem_type'=>$problem_name);
		return $answer;
		

	}
	private function _segment_similality_document($doc_id)
	{
		$doc_id=(is_array($doc_id))? "IN (".implode(',',$doc_id).")":"=".$doc_id;		
		$sql="SELECT problem_type FROM tb_document WHERE substring(name_abbr,2) ".$doc_id;	
		$rs=mysql_query($sql);
		while($p=mysql_fetch_assoc($rs)){
			$problem_type[]=$p['problem_type'];
		}
		return $problem_type;
		
		 
	}
	
	
	
	
    private function _segment_by_dictionary($input_array) {

        $result_array = array();
        $tmp_string = '';

        $pointer = 0;
        $length_of_string = count($input_array)-1;

        while ($pointer <= $length_of_string) {

            $tmp_string .= $input_array[$pointer];

            if (isset($this->_dictionary_array[crc32($tmp_string)])) { // ถ้าเจอใน Dict //
                $dup_array = array();
                $dup_array[] = array(
                    'title' => $tmp_string,
                    'to_mark' => $pointer + 1,
                );
                $count_more = 0;
                $more_tmp = $tmp_string;


                for ($i = $pointer + 1; $i <= $length_of_string; $i++) {
                    $more_tmp .= $input_array[$i];

                    if (isset($this->_dictionary_array[crc32($more_tmp)])) {
                        $dup_array[] = array(
                            'title' => $more_tmp,
                            'to_mark' => $i + 1,
                        );
                        
                    }

                    $count_more++;
                }

                if (count($dup_array) > 0) {
                    $result_array[] = $dup_array[count($dup_array) - 1]['title'];

                    $pointer = $dup_array[count($dup_array) - 1]['to_mark'];


                } else {
                    
                }

                $dup_array = array();
                $tmp_string = '';
                continue;
            }

            $pointer++;
        }

        if ($tmp_string != '') { //  ส่วนที่เหลือ ถ้าไม่เจอใน Dict
            $result_array[] = $tmp_string;
        }

        if (count($result_array) == 0) {
            return array(implode($input_array));
        }
        return $result_array;
    }

    private function _segment_by_dictionary_reverse($input_array) {

        $result_array = array();
        $tmp_string = '';

        $pointer = 0;
        $length_of_string = count($input_array)-1;

        while ($pointer <= $length_of_string) {

            $tmp_string = $input_array[$pointer] . $tmp_string;

            if (isset($this->_dictionary_array[crc32($tmp_string)])) { // ถ้าเจอใน Dict //
                $dup_array = array();
                $dup_array[] = array(
                    'title' => $tmp_string,
                    'to_mark' => $pointer + 1,
                );
                $count_more = 0;
                $more_tmp = $tmp_string;



                for ($i = $pointer + 1; $i <= $length_of_string; $i++) {
                    $more_tmp = $input_array[$i] . $more_tmp;
                    //echo $more_tmp.'<br/>';
                    //echo $more_tmp.'<br/>';
                    if (isset($this->_dictionary_array[crc32($more_tmp)])) {
                        $dup_array[] = array(
                            'title' => $more_tmp,
                            'to_mark' => $i + 1,
                        );

                    }

                    $count_more++;
                }

                if (count($dup_array) > 0) {
                    $result_array[] = $dup_array[count($dup_array) - 1]['title'];

                    $pointer = $dup_array[count($dup_array) - 1]['to_mark'];


                } else {
                    
                }

                $dup_array = array();
                $tmp_string = '';
                continue;
            }

            $pointer++;
        }

        if ($tmp_string != '') { //  ส่วนที่เหลือ ถ้าไม่เจอใน Dict
            $result_array[] = $tmp_string;
        }

        if (count($result_array) == 0) {
            return array(implode(array_reverse($input_array)));
        }
        return array_reverse($result_array);
    }

}
